﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace engine
{

    #region powerpoint专用
    public class PresentationUnit : Unit
    {
        public PresentationUnit()
            : base(UnitType.Body)
        {
        }
    }

    public class SlideUnit : Unit
    {
        public SlideUnit()
            : base(UnitType.Body)
        {
        }
    }
    #endregion

    #region excel专用
    public class WorkbookUnit : Unit
    {
        public WorkbookUnit()
            : base(UnitType.Body)
        {

        }
    }

    public class WorksheetUnit : Unit
    {
        public List<TextBoxUnit> TextBoxs { get; set; }
        public TableUnit Table { get; set; }
        public List<PictureUnit> Pictures { get; set; }

        public WorksheetUnit()
            : base(UnitType.Body)
        {
            TextBoxs = new List<TextBoxUnit>();
            Table = new TableUnit();
            Pictures = new List<PictureUnit>();
        }
    }
    #endregion

    #region word专用
    public class DocumentUnit : Unit
    {
        public List<TextBoxUnit> TextBoxs { get; set; }

        public DocumentUnit()
            : base(UnitType.Body)
        {
            TextBoxs = new List<TextBoxUnit>();
        }
    }

    public class SectionUnit : Unit
    {
        public SectionUnit()
            : base(UnitType.Body)
        {
        }
    }
    #endregion

    #region Unit 通用结构节点
    public enum UnitType
    {
        Any,
        String,
        FullString,
        Number,
        Array,
        Object,
        Boolean,
        TextRange,
        Picture,
        Paragraph,
        Table,
        Row,
        Column,
        Cell,
        Body
    }

    public enum MatchStatus
    {
        None,
        Matched,
        Failed
    }

    public abstract class Unit
    {
        public UnitType UnitType { get; private set; }
        public Unit Parent { get; set; }
        public virtual List<Unit> Children { get; set; }
        public Unit Prev { get; set; }
        public Unit Next { get; set; }
        public object Source { get; set; }
        public object SourceParent { get; set; }
        public bool JustSource { get; set; }

        /// <summary>
        /// 匹配状态
        /// 实际使用时，分多种情况
        /// 当不是函数匹配时，如果是文本或图片节点需要在匹配器DataMatcher里设置匹配状态，其余节点直接在NodeBase中将第一个元素置为已匹配即可
        /// 当是函数匹配时，如果是变量则在FuncNode中设值已匹配，如果是函数则在TemplateFunc中设置匹配状态
        /// </summary>
        public MatchStatus MatchStatus { get; set; }

        public Unit(UnitType unitType)
        {
            UnitType = unitType;
            Children = new List<Unit>();
            MatchStatus = MatchStatus.None;
        }

        public void AddChild(Unit child)
        {
            Unit prev = Children.LastOrDefault();
            if(prev != null)
            {
                child.Prev = prev;
                prev.Next = child;
            }
            this.Children.Add(child);
            child.Parent = this;
        }

        public override string ToString()
        {
            string result = "";
            foreach(var child in Children)
            {
                if(child is ParagraphUnit && result.Length > 0)
                {
                    result += "\n";
                }
                result += child.ToString();
            }
            return result;
        }
    }

    public class TextBoxUnit : Unit
    {
        public TextBoxUnit()
            : base(UnitType.Body)
        {
        }
    }

    public class RowUnit : Unit
    {
        public List<Unit> Cells
        {
            get
            {
                return Children;
            }
        }
        public RowUnit()
            : base(UnitType.Row)
        {
        }
    }

    public class CellUnit : Unit
    {
        public CellFormat CellFormat { get; set; }

        public CellUnit()
            : base(UnitType.Cell|UnitType.Body)
        {
            CellFormat = new CellFormat();
        }
    }

    public class TableUnit : Unit
    {
        public List<Unit> Rows
        {
            get
            {
                return Children;
            }
        }

        public int ColumnCount { get; set; }

        public TableUnit()
            : base(UnitType.Table)
        {
        }
    }

    public class BodyUnit : Unit
    {
        public BodyUnit()
            : base(UnitType.Body)
        {

        }
    }

    public class ParagraphUnit : Unit
    {
        public CharactorFormat CharactorFormat { get; set; }

        public ParagraphUnit()
            : base(UnitType.Paragraph)
        {

        }
    }

    public class PictureUnit : Unit
    {
        public Image Image { get; set; }
        public string Path { get; set; }

        public double Width { get; set; }
        public double Height { get; set; }

        public PictureUnit()
            : base(UnitType.Picture)
        {

        }
    }

    public class TextRangeUnit : Unit
    {
        public string Text { get; set; }
        public int MatchIndex { get; set; }
        public CharactorFormat CharactorFormat { get; set; }

        public TextRangeUnit()
            : base(UnitType.TextRange)
        {

        }

        public override string ToString()
        {
            return Text;
        }
    }

    public class FullString : ConvertibleBase
    {
        public List<Unit> Items { get; set; }

        public FullString()
        {
            Items = new List<Unit>();
        }

        public override string ToString(IFormatProvider provider)
        {
            return this.ToString();
        }

        public override string ToString()
        {
            string result = "";
            foreach (var item in Items)
            {
                result += item.ToString();
            }
            return result;
        }
    }

    public class CellFormat
    {
        public double Border { get; set; }
        public Color Color { get; set; }
    }

    public class CharactorFormat
    {
        public double FontSize { get; set; }
    }

    public class ConvertibleBase : IConvertible
    {
        public virtual TypeCode GetTypeCode()
        {
            throw new NotImplementedException();
        }

        public virtual bool ToBoolean(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual byte ToByte(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual char ToChar(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual DateTime ToDateTime(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual decimal ToDecimal(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual double ToDouble(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual short ToInt16(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual int ToInt32(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual long ToInt64(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual sbyte ToSByte(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual float ToSingle(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual string ToString(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual object ToType(Type conversionType, IFormatProvider provider)
        {
            if (conversionType == typeof(object))
            {
                return this;
            }
            else
            {
                return this;
            }
        }

        public virtual ushort ToUInt16(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual uint ToUInt32(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }

        public virtual ulong ToUInt64(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
    }
    #endregion
}
